package org.example.compare.schedule;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.example.compare.dto.OrderDto;
import org.example.compare.dto.OrderProcess;
import org.example.compare.dto.ProcessSch;
import org.example.compare.dto.SBoxData;
import org.example.compare.global.Global;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 测试数据生成器类，用于生成calcuteTarget函数的测试数据
 */
public class CalcuteTargetTestDataGenerator {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 生成随机测试数据并保存到文件
     */
    public static void generateRandomTestData(int iteration) throws IOException {
        String basePath = "../../test_data/calcuteTarget/random_case_" + iteration;
        File baseDir = new File(basePath);
        if (!baseDir.exists()) {
            baseDir.mkdirs();
        }

        Random random = new Random();

        // 设置全局变量
        Global.gRuleHourTargetWindow = 4;
        Global.gFeedCyclePercent = 3;

        // 生成SchData.orderProcessAllDependency数据
        Map<String, List<Map<String, Object>>> orderProcessAllDependency = new HashMap<>();

        // 随机生成5-10个工序
        int processCount = 5 + random.nextInt(6);
        List<Long> processIds = new ArrayList<>();
        for (int i = 0; i < processCount; i++) {
            processIds.add((long) (1000 + i));
        }

        // 为每个工序生成前置工序依赖，避免循环依赖
        for (int idx = 0; idx < processIds.size(); idx++) {
            Long processId = processIds.get(idx);
            
            // 70%概率有前置工序，30%概率没有前置工序
            if (random.nextInt(10) < 7) {
                List<Map<String, Object>> dependencies = new ArrayList<>();

                // 随机决定该工序有多少个前置工序 (1-3个)
                int dependencyCount = random.nextInt(3) + 1;
                
                // 只能依赖于它之前的工序，避免循环依赖
                if (idx > 0) {
                    int maxDependencies = Math.min(dependencyCount, idx);
                    Set<Long> usedDependencies = new HashSet<>();
                    
                    for (int i = 0; i < maxDependencies; i++) {
                        // 随机选择一个前置工序（只能选择当前工序之前的工序）
                        Long dependencyId;
                        do {
                            int depIndex = random.nextInt(idx);
                            dependencyId = processIds.get(depIndex);
                        } while (usedDependencies.contains(dependencyId));

                        usedDependencies.add(dependencyId);

                        // 创建前置工序数据
                        Map<String, Object> dependency = new HashMap<>();
                        dependency.put("orderProcessId", dependencyId);
                        dependency.put("mfProcessTotalTime", 100.0 + random.nextInt(900)); // 100-1000的随机总工时

                        dependencies.add(dependency);
                    }
                }

                orderProcessAllDependency.put(processId.toString(), dependencies);
            }
            // 30%概率不添加到orderProcessAllDependency中，表示没有前置工序依赖
        }

        // 保存orderProcessAllDependency到文件
        objectMapper.writeValue(new File(basePath + "/order_process_all_dependency.json"), orderProcessAllDependency);

        // 生成函数输入参数OrderDto
        OrderDto orderDto = generateRandomOrderDto(random, processIds);

        // 保存OrderDto到文件
        objectMapper.writeValue(new File(basePath + "/testCases.json"), orderDto);

        // 保存全局变量到文件
        Map<String, Integer> globalVariables = new HashMap<>();
        globalVariables.put("gRuleHourTargetWindow", Global.gRuleHourTargetWindow);
        globalVariables.put("gFeedCyclePercent", Global.gFeedCyclePercent);
        objectMapper.writeValue(new File(basePath + "/global_variables.json"), globalVariables);
    }

    /**
     * 生成随机OrderDto对象
     */
    private static OrderDto generateRandomOrderDto(Random random, List<Long> processIds) {
        OrderDto orderDto = OrderDto.InitOrder();

        // 设置基本属性
        orderDto.setMiOperate2Deadline(3600 + random.nextInt(24 * 3600)); // 1小时到1天的秒数
        orderDto.setMiNow2DeadlineSecs(random.nextInt(orderDto.getMiOperate2Deadline())); // 现在到截止时间的秒数
        orderDto.setMiTotalPlanCnt(100 + random.nextInt(900)); // 总计划件数100-1000

        // 生成随机的筐数据
        Map<Long, List<SBoxData>> boxSetGroupByPart = new HashMap<>();
        int partCount = 1 + random.nextInt(3); // 1-3个部件

        for (int partIndex = 0; partIndex < partCount; partIndex++) {
            Long partId = (long) (100 + partIndex);
            List<SBoxData> boxes = new ArrayList<>();

            int boxCount = 1 + random.nextInt(5); // 每个部件1-5个筐
            for (int boxIndex = 0; boxIndex < boxCount; boxIndex++) {
                SBoxData box = new SBoxData();
                box.setMiBoxRecordId(10000 + partIndex * 100 + boxIndex);
                box.setMBoxNum("BOX-" + partIndex + "-" + boxIndex);
                box.setPartId(partId);
                box.setMiPlanCnt(10 + random.nextInt(90)); // 每筐计划件数10-100
                boxes.add(box);
            }

            boxSetGroupByPart.put(partId, boxes);
        }
        orderDto.setMCurBoxSetGroupByPart(boxSetGroupByPart);

        // 生成随机的工序数据
        Map<Long, Map<Integer, OrderProcess>> orderProcessSetGroupByPart = new HashMap<>();

        for (int partIndex = 0; partIndex < partCount; partIndex++) {
            Long partId = (long) (100 + partIndex);
            Map<Integer, OrderProcess> processMap = new HashMap<>();

            // 每个部件2-5个工序
            int processCount = 2 + random.nextInt(4);
            for (int processIndex = 0; processIndex < processCount; processIndex++) {
                OrderProcess process = OrderProcess.InitOrderProcess(orderDto);
                process.setOrderProcessId(processIds.get(random.nextInt(processIds.size())));
                process.setMfProcessTotalTime(100.0f + random.nextInt(900)); // 总工时100-1000
                process.setMiFinishedCnt(random.nextInt(orderDto.getMiTotalPlanCnt())); // 已完成件数
                process.setMiPartSeqNum(processIndex);
                process.setMPartId(partId);

                // 初始化调度对象
                ProcessSch scheduling = new ProcessSch();
                process.setMScheduling(scheduling);

                processMap.put(processIndex, process);
            }

            orderProcessSetGroupByPart.put(partId, processMap);
        }
        orderDto.setMOrderProcessSetGroupByPart(orderProcessSetGroupByPart);

        return orderDto;
    }

    /**
     * 生成手动测试案例数据并保存到文件
     */
    public static void generateManualTestData(int caseNumber) throws IOException {
        String basePath = "../../test_data/calcuteTarget/manual_case_" + caseNumber;
        File baseDir = new File(basePath);
        if (!baseDir.exists()) {
            baseDir.mkdirs();
        }

        if (caseNumber == 1) {
            // 案例1: 简单的订单，包含少量工序和筐
            generateManualTestCase1(basePath);
        } else if (caseNumber == 2) {
            // 案例2: 复杂的订单，包含多个部件、多个工序和筐
            generateManualTestCase2(basePath);
        }
    }

    /**
     * 生成手动测试案例1
     */
    private static void generateManualTestCase1(String basePath) throws IOException {
        // 设置全局变量
        Global.gRuleHourTargetWindow = 4;
        Global.gFeedCyclePercent = 3;

        // 生成SchData.orderProcessAllDependency数据
        Map<String, List<Map<String, Object>>> orderProcessAllDependency = new HashMap<>();

        // 定义工序依赖关系（有向无环图）
        // 工序1001: 无前置工序
        orderProcessAllDependency.put("1001", new ArrayList<>());

        // 工序1002: 依赖工序1001
        List<Map<String, Object>> dependencies1002 = new ArrayList<>();
        Map<String, Object> dep1001 = new HashMap<>();
        dep1001.put("orderProcessId", 1001L);
        dep1001.put("mfProcessTotalTime", 200.0);
        dependencies1002.add(dep1001);
        orderProcessAllDependency.put("1002", dependencies1002);

        // 工序1003: 依赖工序1001和1002
        List<Map<String, Object>> dependencies1003 = new ArrayList<>();
        Map<String, Object> dep1003_1 = new HashMap<>();
        dep1003_1.put("orderProcessId", 1001L);
        dep1003_1.put("mfProcessTotalTime", 200.0);
        dependencies1003.add(dep1003_1);

        Map<String, Object> dep1003_2 = new HashMap<>();
        dep1003_2.put("orderProcessId", 1002L);
        dep1003_2.put("mfProcessTotalTime", 300.0);
        dependencies1003.add(dep1003_2);
        orderProcessAllDependency.put("1003", dependencies1003);

        // 保存orderProcessAllDependency到文件
        objectMapper.writeValue(new File(basePath + "/order_process_all_dependency.json"), orderProcessAllDependency);

        // 生成OrderDto
        OrderDto orderDto = OrderDto.InitOrder();
        orderDto.setMiOperate2Deadline(8 * 3600); // 8小时
        orderDto.setMiNow2DeadlineSecs(2 * 3600); // 已过去2小时
        orderDto.setMiTotalPlanCnt(200); // 总计划件数200

        // 生成筐数据
        Map<Long, List<SBoxData>> boxSetGroupByPart = new HashMap<>();
        List<SBoxData> boxes = new ArrayList<>();

        SBoxData box1 = new SBoxData();
        box1.setMiBoxRecordId(10001);
        box1.setMBoxNum("BOX-1");
        box1.setPartId(100L);
        box1.setMiPlanCnt(100);
        boxes.add(box1);

        SBoxData box2 = new SBoxData();
        box2.setMiBoxRecordId(10002);
        box2.setMBoxNum("BOX-2");
        box2.setPartId(100L);
        box2.setMiPlanCnt(100);
        boxes.add(box2);

        boxSetGroupByPart.put(100L, boxes);
        orderDto.setMCurBoxSetGroupByPart(boxSetGroupByPart);

        // 生成工序数据
        Map<Long, Map<Integer, OrderProcess>> orderProcessSetGroupByPart = new HashMap<>();
        Map<Integer, OrderProcess> processMap = new HashMap<>();

        // 工序1001
        OrderProcess process1 = OrderProcess.InitOrderProcess(orderDto);
        process1.setOrderProcessId(1001L);
        process1.setMfProcessTotalTime(200.0f);
        process1.setMiFinishedCnt(50);
        process1.setMiPartSeqNum(1);
        process1.setMPartId(100L);
        process1.setMScheduling(new ProcessSch());
        processMap.put(1, process1);

        // 工序1002
        OrderProcess process2 = OrderProcess.InitOrderProcess(orderDto);
        process2.setOrderProcessId(1002L);
        process2.setMfProcessTotalTime(300.0f);
        process2.setMiFinishedCnt(30);
        process2.setMiPartSeqNum(2);
        process2.setMPartId(100L);
        process2.setMScheduling(new ProcessSch());
        processMap.put(2, process2);

        // 工序1003
        OrderProcess process3 = OrderProcess.InitOrderProcess(orderDto);
        process3.setOrderProcessId(1003L);
        process3.setMfProcessTotalTime(250.0f);
        process3.setMiFinishedCnt(20);
        process3.setMiPartSeqNum(3);
        process3.setMPartId(100L);
        process3.setMScheduling(new ProcessSch());
        processMap.put(3, process3);

        orderProcessSetGroupByPart.put(100L, processMap);
        orderDto.setMOrderProcessSetGroupByPart(orderProcessSetGroupByPart);

        // 保存OrderDto到文件
        objectMapper.writeValue(new File(basePath + "/testCases.json"), orderDto);

        // 保存全局变量到文件
        Map<String, Integer> globalVariables = new HashMap<>();
        globalVariables.put("gRuleHourTargetWindow", Global.gRuleHourTargetWindow);
        globalVariables.put("gFeedCyclePercent", Global.gFeedCyclePercent);
        objectMapper.writeValue(new File(basePath + "/global_variables.json"), globalVariables);
    }

    /**
     * 生成手动测试案例2
     */
    private static void generateManualTestCase2(String basePath) throws IOException {
        // 设置全局变量
        Global.gRuleHourTargetWindow = 4;
        Global.gFeedCyclePercent = 3;

        // 生成SchData.orderProcessAllDependency数据
        Map<String, List<Map<String, Object>>> orderProcessAllDependency = new HashMap<>();

        // 定义工序依赖关系（有向无环图）
        // 工序2001: 无前置工序
        orderProcessAllDependency.put("2001", new ArrayList<>());

        // 工序2002: 依赖工序2001
        List<Map<String, Object>> dependencies2002 = new ArrayList<>();
        Map<String, Object> dep2001 = new HashMap<>();
        dep2001.put("orderProcessId", 2001L);
        dep2001.put("mfProcessTotalTime", 200.0);
        dependencies2002.add(dep2001);
        orderProcessAllDependency.put("2002", dependencies2002);

        // 工序2003: 依赖工序2001
        List<Map<String, Object>> dependencies2003 = new ArrayList<>();
        Map<String, Object> dep2003 = new HashMap<>();
        dep2003.put("orderProcessId", 2001L);
        dep2003.put("mfProcessTotalTime", 150.0);
        dependencies2003.add(dep2003);
        orderProcessAllDependency.put("2003", dependencies2003);

        // 工序2004: 依赖工序2002和2003
        List<Map<String, Object>> dependencies2004 = new ArrayList<>();
        Map<String, Object> dep2004_1 = new HashMap<>();
        dep2004_1.put("orderProcessId", 2002L);
        dep2004_1.put("mfProcessTotalTime", 300.0);
        dependencies2004.add(dep2004_1);

        Map<String, Object> dep2004_2 = new HashMap<>();
        dep2004_2.put("orderProcessId", 2003L);
        dep2004_2.put("mfProcessTotalTime", 250.0);
        dependencies2004.add(dep2004_2);
        orderProcessAllDependency.put("2004", dependencies2004);

        // 工序3001: 无前置工序
        orderProcessAllDependency.put("3001", new ArrayList<>());

        // 工序3002: 依赖工序3001
        List<Map<String, Object>> dependencies3002 = new ArrayList<>();
        Map<String, Object> dep3001 = new HashMap<>();
        dep3001.put("orderProcessId", 3001L);
        dep3001.put("mfProcessTotalTime", 150.0);
        dependencies3002.add(dep3001);
        orderProcessAllDependency.put("3002", dependencies3002);

        // 保存orderProcessAllDependency到文件
        objectMapper.writeValue(new File(basePath + "/order_process_all_dependency.json"), orderProcessAllDependency);

        // 生成OrderDto
        OrderDto orderDto = OrderDto.InitOrder();
        orderDto.setMiOperate2Deadline(12 * 3600); // 12小时
        orderDto.setMiNow2DeadlineSecs(4 * 3600); // 已过去4小时
        orderDto.setMiTotalPlanCnt(500); // 总计划件数500

        // 生成筐数据 (两个部件)
        Map<Long, List<SBoxData>> boxSetGroupByPart = new HashMap<>();

        // 部件1的筐
        List<SBoxData> boxes1 = new ArrayList<>();
        SBoxData box1 = new SBoxData();
        box1.setMiBoxRecordId(20001);
        box1.setMBoxNum("BOX-1-1");
        box1.setPartId(200L);
        box1.setMiPlanCnt(150);
        boxes1.add(box1);

        SBoxData box2 = new SBoxData();
        box2.setMiBoxRecordId(20002);
        box2.setMBoxNum("BOX-1-2");
        box2.setPartId(200L);
        box2.setMiPlanCnt(150);
        boxes1.add(box2);
        boxSetGroupByPart.put(200L, boxes1);

        // 部件2的筐
        List<SBoxData> boxes2 = new ArrayList<>();
        SBoxData box3 = new SBoxData();
        box3.setMiBoxRecordId(30001);
        box3.setMBoxNum("BOX-2-1");
        box3.setPartId(300L);
        box3.setMiPlanCnt(200);
        boxes2.add(box3);
        boxSetGroupByPart.put(300L, boxes2);

        orderDto.setMCurBoxSetGroupByPart(boxSetGroupByPart);

        // 生成工序数据 (两个部件)
        Map<Long, Map<Integer, OrderProcess>> orderProcessSetGroupByPart = new HashMap<>();

        // 部件1的工序
        Map<Integer, OrderProcess> processMap1 = new HashMap<>();
        OrderProcess process1_1 = OrderProcess.InitOrderProcess(orderDto);
        process1_1.setOrderProcessId(2001L);
        process1_1.setMfProcessTotalTime(200.0f);
        process1_1.setMiFinishedCnt(80);
        process1_1.setMiPartSeqNum(1);
        process1_1.setMPartId(200L);
        process1_1.setMScheduling(new ProcessSch());
        processMap1.put(1, process1_1);

        OrderProcess process1_2 = OrderProcess.InitOrderProcess(orderDto);
        process1_2.setOrderProcessId(2002L);
        process1_2.setMfProcessTotalTime(300.0f);
        process1_2.setMiFinishedCnt(60);
        process1_2.setMiPartSeqNum(2);
        process1_2.setMPartId(200L);
        process1_2.setMScheduling(new ProcessSch());
        processMap1.put(2, process1_2);

        OrderProcess process1_3 = OrderProcess.InitOrderProcess(orderDto);
        process1_3.setOrderProcessId(2003L);
        process1_3.setMfProcessTotalTime(250.0f);
        process1_3.setMiFinishedCnt(50);
        process1_3.setMiPartSeqNum(3);
        process1_3.setMPartId(200L);
        process1_3.setMScheduling(new ProcessSch());
        processMap1.put(3, process1_3);

        OrderProcess process1_4 = OrderProcess.InitOrderProcess(orderDto);
        process1_4.setOrderProcessId(2004L);
        process1_4.setMfProcessTotalTime(400.0f);
        process1_4.setMiFinishedCnt(30);
        process1_4.setMiPartSeqNum(4);
        process1_4.setMPartId(200L);
        process1_4.setMScheduling(new ProcessSch());
        processMap1.put(4, process1_4);

        orderProcessSetGroupByPart.put(200L, processMap1);

        // 部件2的工序
        Map<Integer, OrderProcess> processMap2 = new HashMap<>();
        OrderProcess process2_1 = OrderProcess.InitOrderProcess(orderDto);
        process2_1.setOrderProcessId(3001L);
        process2_1.setMfProcessTotalTime(150.0f);
        process2_1.setMiFinishedCnt(100);
        process2_1.setMiPartSeqNum(1);
        process2_1.setMPartId(300L);
        process2_1.setMScheduling(new ProcessSch());
        processMap2.put(1, process2_1);

        OrderProcess process2_2 = OrderProcess.InitOrderProcess(orderDto);
        process2_2.setOrderProcessId(3002L);
        process2_2.setMfProcessTotalTime(350.0f);
        process2_2.setMiFinishedCnt(80);
        process2_2.setMiPartSeqNum(2);
        process2_2.setMPartId(300L);
        process2_2.setMScheduling(new ProcessSch());
        processMap2.put(2, process2_2);

        orderProcessSetGroupByPart.put(300L, processMap2);

        orderDto.setMOrderProcessSetGroupByPart(orderProcessSetGroupByPart);

        // 保存OrderDto到文件
        objectMapper.writeValue(new File(basePath + "/testCases.json"), orderDto);

        // 保存全局变量到文件
        Map<String, Integer> globalVariables = new HashMap<>();
        globalVariables.put("gRuleHourTargetWindow", Global.gRuleHourTargetWindow);
        globalVariables.put("gFeedCyclePercent", Global.gFeedCyclePercent);
        objectMapper.writeValue(new File(basePath + "/global_variables.json"), globalVariables);
    }

    public static void main(String[] args) {
        try {
            // 确保主目录存在
            File mainDir = new File("../../test_data/calcuteTarget");
            if (!mainDir.exists()) {
                mainDir.mkdirs();
            }

            // 生成50组随机测试数据
            for (int i = 1; i <= 50; i++) {
                // 检查是否存在以random_case_i命名的文件夹，没有则创建
                String casePath = "../../test_data/calcuteTarget/random_case_" + i;
                File caseDir = new File(casePath);
                if (!caseDir.exists()) {
                    caseDir.mkdirs();
                }

                generateRandomTestData(i);
                System.out.println("测试数据集 " + i + " 已成功生成并保存到 " + casePath);
            }

            // 生成2个手动测试案例
            for (int i = 1; i <= 2; i++) {
                generateManualTestData(i);
                String casePath = "../../test_data/calcuteTarget/manual_case_" + i;
                System.out.println("手动测试案例 " + i + " 已成功生成并保存到 " + casePath);
            }

            System.out.println("所有测试数据已成功生成并保存到../../test_data/calcuteTarget目录下");
        } catch (IOException e) {
            System.err.println("生成测试数据时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
}